/**
   \file  image.hh
   \brief Encapsulation of images as required by libgist driver program.

   This file defines a class that uses libdevil to load images and then
   converts them to Boost.GIL images. This class is very specific to the
   requirements of libgist and its driver program; it is not a generic
   and reusable image class.
*/

/*
   This file is part of libgist.

   libgist is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2 of the License, or (at your
   option) any later version.

   libgist is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
   for more details.

   You should have received a copy of the GNU General Public License
   along with libgist; if not, write to the Free Software Foundation,
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*/

/*
   REVISION HISTORY

   $HeadURL: http://libgist.googlecode.com/svn/branches/lazebnik_dev/drv/image.hh $
   $Id: image.hh 41 2011-08-22 08:51:48Z libgist@gmail.com $
*/

#ifndef GISTDRV_IMAGE_DOT_HH
#define GISTDRV_IMAGE_DOT_HH

//------------------------------ HEADERS --------------------------------

// gistdrv
#include "exceptions.hh"

// libdevil
#include <IL/il.h>

// Boost.GIL
#include <boost/gil/typedefs.hpp>
#include <boost/gil/image.hpp>

// Standard C++
#include <string>

//----------------------------- NAMESPACE -------------------------------

namespace gistdrv {

//------------------------- CLASS DEFINITION ----------------------------

/**
   \brief Encapsulation of image loading and conversion operations
   required by libgist driver program.

   This class provides a simple API for loading images using libdevil and
   converting them to Boost.GIL images. It is specifically meant for this
   particular program and its requirements. Please do not mistake it for
   some sort of generic and reusable class that can be used to represent
   images.
*/
class image {
   /// libdevil requires us to first generate an image name/ID and bind
   /// that image name to the current image before we can load and
   /// manipulate images. This data member keeps track of this image
   /// object's ID as assigned by libdevil.
   ILuint m_image_id ;

public:
   /**
      \brief Load specified image.
      \param file_name Name of file to load.

      Upon instantiation, we will load the image specified by the given
      file name. The libgist driver program can load any image type
      supported by libdevil. This includes many common image formats such
      as JPG, PNG, TIFF, PNM, etc.

      If the image file cannot be loaded, object construction will fail
      with a load_error exception.
   */
   image(const std::string& file_name) ;

private:
   // Prevent copy and assignment.
   image(const image&) ;
   image& operator=(const image&) ;

public:
   /**
      \brief  Resize currently loaded image to specified dimensions.
      \param  width New image width.
      \param  height New image height.
      \return Reference to the resized (i.e., this) image object.

      This method resizes the currently loaded image to the specified
      dimensions. It returns a reference to this object to allow a series
      of such transformative functions to be chained.
   */
   image& resize(int width, int height) ;

   /**
      \brief  Convert image to grayscale.
      \return Reference to the grayscale (i.e., this) image object.

      This method converts the image to grayscale. It returns a
      reference to this object to allow a series of such transformative
      functions to be chained.
   */
   image& grayscale() ;

   /// This conversion operator automatically produces a Boost.GIL
   /// grayscale image whenever required.
   operator boost::gil::gray8_image_t() const ;

   /// This conversion operator automatically produces a Boost.GIL
   /// RGB image whenever required.
   operator boost::gil::rgb8_image_t() const ;

   /**
      \brief Save current image to specified file.
      \param file_name Name of file to which image should be saved.

      This method saves the image to the specified file. The image format
      should be specified by the extension. The image can be saved to any
      format supported by libdevil (JPG, PNG, TIFF, PNM, etc.).

      If the image file cannot be saved, this function will throw a
      save_error exception.
   */
   void save(const std::string& file_name) const ;

   /// Clean-up: release the libdevil image resources.
   ~image() ;

private:
   // If, for whatever reason, libdevil bombs out trying to load an
   // image, we will report it with an instance of this class.
   struct load_error: public exception {
      load_error(const std::string& file_name) ;
   } ;

   // If, for whatever reason, libdevil bombs out trying to save an
   // image, we will report it with an instance of this class.
   struct save_error: public exception {
      save_error(const std::string& file_name) ;
   } ;
} ;

//-----------------------------------------------------------------------

} // end of namespace encapsulating this file's definitions

#endif

/* So things look consistent in everyone's emacs... */
/* Local Variables: */
/* indent-tabs-mode: nil */
/* End: */
